// cmd/root.go
package cmd

import (
	"fmt"
	"net/http"
	"os"
	"time"
	"weikjie/my_blog/config"
	"weikjie/my_blog/logger"

	"github.com/gin-gonic/gin"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"go.uber.org/zap"
)

var (
	configPath string // 配置文件路径
)

// 根命令
var rootCmd = &cobra.Command{
	Use:   "main", // 命令名称（如 ./main --config=xxx）
	Short: "A Gin app with configurable config file",
	Long:  "A Gin application that supports specifying config file on startup",
	Run: func(cmd *cobra.Command, args []string) {
		// 加载配置
		if err := loadConfig(); err != nil {
			fmt.Printf("Failed to load config: %v\n", err)
			os.Exit(1)
		}
		defer logger.GetLogger().Sync()

		// 初始化Gin
		r := initGin()

		// 注册路由
		registerRoutes(r)

		// 启动服务
		startServer(r)
	},
}

// 初始化命令（设置参数）
func init() {
	// 添加--config参数，指定配置文件路径（默认值为config/config.yaml）
	rootCmd.Flags().StringVarP(&configPath, "config", "c", "config/config.yaml", "path to config file (default: config/config.yaml)")
}

// Initialize zap logger
func initLogger() error {
	if err := logger.InitLogger(config.GetConfig().Server.Env); err != nil {
		return fmt.Errorf("failed to initialize zap logger: %w", err)
	}
	return nil
}

// 加载配置文件到cfg变量
func loadConfig() error {
	// 设置Viper读取的配置文件路径
	viper.SetConfigFile(configPath)

	// 读取配置文件
	if err := viper.ReadInConfig(); err != nil {
		return fmt.Errorf("read config file failed: %w", err)
	}

	// 将配置解析到结构体
	var cfg config.Config
	if err := viper.Unmarshal(&cfg); err != nil {
		return fmt.Errorf("unmarshal config to struct failed: %w", err)
	}
	config.SetConfig(&cfg)

	// Initialize logger after config is loaded
	if err := initLogger(); err != nil {
		return err
	}

	logger.GetLogger().Info("Config loaded successfully")

	return nil
}

// 初始化Gin引擎（根据环境设置模式）
func initGin() *gin.Engine {
	// 根据配置的env设置Gin模式（dev: debug模式，prod: release模式）
	if config.GetConfig().Server.Env == "prod" {
		gin.SetMode(gin.ReleaseMode)
	} else {
		gin.SetMode(gin.DebugMode)
	}

	r := gin.New()

	// Create a SugaredLogger for Gin
	sugar := logger.GetLogger().Named("gin").WithOptions(zap.AddCallerSkip(1)).Sugar()

	// Add zap logger middleware using a custom writer
	r.Use(gin.LoggerWithConfig(gin.LoggerConfig{
		Output: logger.NewZapLoggerWriter(sugar),
	}))

	// Recovery middleware
	r.Use(gin.Recovery())
	return r
}

// 注册路由示例
func registerRoutes(r *gin.Engine) {
	// 健康检查接口
	r.GET("/health", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"status":  "ok",
			"env":     config.GetConfig().Server.Env,
			"port":    config.GetConfig().Server.Port,
			"message": "Gin app is running",
		})
	})
}

// 启动HTTP服务
func startServer(r *gin.Engine) {
	srv := &http.Server{
		Addr:         fmt.Sprintf(":%d", config.GetConfig().Server.Port),
		Handler:      r,
		ReadTimeout:  time.Duration(config.GetConfig().Server.ReadTimeout) * time.Second,
		WriteTimeout: time.Duration(config.GetConfig().Server.WriteTimeout) * time.Second,
	}

	fmt.Printf("Server is starting on %s (env: %s)\n", srv.Addr, config.GetConfig().Server.Env)
	if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		fmt.Printf("Failed to start server: %v\n", err)
		os.Exit(1)
	}
}

// 执行根命令（供main.go调用）
func Execute() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Printf("Error: %v\n", err)
		os.Exit(1)
	}
}
